#ifndef IMAGE_H
#define IMAGE_H

#include "esp_camera.h"
#include <base64.h>
#include <ArduinoJson.h>
#include "cJSON.h"
#include <HTTPClient.h>
#include "Gpt.h"
#include "Tts.h"
#define CAMERA_MODEL_XIAO_ESP32S3 // Has PSRAM
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 10
#define SIOD_GPIO_NUM 40
#define SIOC_GPIO_NUM 39

#define Y9_GPIO_NUM 48
#define Y8_GPIO_NUM 11
#define Y7_GPIO_NUM 12
#define Y6_GPIO_NUM 14
#define Y5_GPIO_NUM 16
#define Y4_GPIO_NUM 18
#define Y3_GPIO_NUM 17
#define Y2_GPIO_NUM 15
#define VSYNC_GPIO_NUM 38
#define HREF_GPIO_NUM 47
#define PCLK_GPIO_NUM 13
#define LED_GPIO_NUM 21
bool camera_sign = false; // Check camera status


bool cam_intialization(void)
{
    Serial.println("Starting Camera");
    camera_config_t config;
    config.ledc_channel = LEDC_CHANNEL_0;
    config.ledc_timer = LEDC_TIMER_0;
    config.pin_d0 = Y2_GPIO_NUM;
    config.pin_d1 = Y3_GPIO_NUM;
    config.pin_d2 = Y4_GPIO_NUM;
    config.pin_d3 = Y5_GPIO_NUM;
    config.pin_d4 = Y6_GPIO_NUM;
    config.pin_d5 = Y7_GPIO_NUM;
    config.pin_d6 = Y8_GPIO_NUM;
    config.pin_d7 = Y9_GPIO_NUM;
    config.pin_xclk = XCLK_GPIO_NUM;
    config.pin_pclk = PCLK_GPIO_NUM;
    config.pin_vsync = VSYNC_GPIO_NUM;
    config.pin_href = HREF_GPIO_NUM;
    config.pin_sscb_sda = SIOD_GPIO_NUM;
    config.pin_sscb_scl = SIOC_GPIO_NUM;
    config.pin_pwdn = PWDN_GPIO_NUM;
    config.pin_reset = RESET_GPIO_NUM;
    config.xclk_freq_hz = 20000000;
    config.frame_size = FRAMESIZE_UXGA;
    config.pixel_format = PIXFORMAT_JPEG; // for streaming
    config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
    config.fb_location = CAMERA_FB_IN_PSRAM;
    config.jpeg_quality = 12;
    config.fb_count = 1;

    // if PSRAM IC present, init with UXGA resolution and higher JPEG quality
    //                      for larger pre-allocated frame buffer.
    if (config.pixel_format == PIXFORMAT_JPEG)
    {
        if (psramFound())
        {
            config.jpeg_quality = 10;
            config.fb_count = 2;
            // config.grab_mode = CAMERA_GRAB_LATEST;
        }
        else
        {
            // Limit the frame size when PSRAM is not available
            config.frame_size = FRAMESIZE_SVGA;
            config.fb_location = CAMERA_FB_IN_DRAM;
        }
    }
    else
    {
        // Best option for face detection/recognition
        config.frame_size = FRAMESIZE_240X240;
#if CONFIG_IDF_TARGET_ESP32S3
        config.fb_count = 2;
#endif
    }

    // camera init
    esp_err_t err = esp_camera_init(&config);
    if (err != ESP_OK)
    {
        Serial.printf("Camera init failed with error 0x%x", err);
        camera_sign = false;
        return camera_sign;
    }
    else
    {
        Serial.println("Camera Ready");
        camera_sign = true; // Camera initialization check passes
        return camera_sign;
    }
}

String image_request(void) // 发送请求，返回的是请求结果代码，该码要填入下一个函数中（change是图片数据（jpg）
{
    // Take a photo
    camera_fb_t *fb = esp_camera_fb_get();
    String change = base64::encode(fb->buf, fb->len);
    Serial.println("image_base64 success");
    memset(data_json, '\0', sizeof(data_json)); // 清空数组
    change.replace("\r\n", "");                 // 移除换行符

    strcat(data_json, "{\"model\":\"qwen-vl-plus\",\"messages\":[{\"role\":\"user\",\"content\":[");
    strcat(data_json, "{\"type\":\"image_url\",\"image_url\":{\"url\":\"data:image/jpeg;base64,");
    strcat(data_json, change.c_str()); // 添加base64编码数据
    strcat(data_json, "\"}},");
    strcat(data_json, "{\"type\":\"text\",\"text\":\"介绍这张图片包涵的内容,要求严格控制在100字符以内。\"}]}]}");
    // Serial.println(data_json);
    // delay(2000);
    HTTPClient http_image_request;
    http_image_request.setTimeout(20000);
    http_image_request.begin(ali_image_apiUrl);
    http_image_request.addHeader("Content-Type", "application/json");
    http_image_request.addHeader("Authorization", String("Bearer ") + String(ali_apiKey));

    int httpCode = http_image_request.POST(data_json);
    if (httpCode == 200)
    {

        String response = http_image_request.getString();
        http_image_request.end();
        JsonDocument jsonDoc;
        deserializeJson(jsonDoc, response);
        // Serial.println(response);
        String id = jsonDoc["choices"][0]["message"]["content"];
        // 设置标志变量和显示文本
        if (xSemaphore != NULL)
        {
            xSemaphoreTake(xSemaphore, portMAX_DELAY);
            displayText = String("I:" + id);
            updateDisplayFlag = true;
            xSemaphoreGive(xSemaphore);
        }
        return id;
    }
    else
    {
        Serial.println("error request" + String(httpCode));
        http_image_request.end();
        return "error";
    }
}

#endif
